/*
 * sp007.cpp
 *
 *  Created on: 2012-11-27
 *      Author: feng
 */



#include "sample.h"

CSp007::CSp007(unsigned int w,unsigned int h):CSample(w,h) {
	GLfloat temp[] = {-75.0f,150.0f,-50.0f,0.0f};
	m3dCopyVector4(m_LightPos,temp);
}

void CSp007::InitOpenGL() {
	GLfloat  ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
	GLfloat  diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
	GLfloat  specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
	GLfloat  specref[] =  { 1.0f, 1.0f, 1.0f, 1.0f };

	// Any three points on the ground (counter clockwise order)
	M3DVector3f points[3] = { { -30.0f, -149.0f, -20.0f }, { -30.0f, -149.0f,
			20.0f }, { 40.0f, -149.0f, 20.0f } };

	glEnable(GL_DEPTH_TEST);	// Hidden surface removal
	glFrontFace(GL_CCW);		// Counter clock-wise polygons face out
	glEnable(GL_CULL_FACE);		// Do not calculate inside of jet

	// Setup and enable light 0
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
	glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
	glLightfv(GL_LIGHT0, GL_POSITION, m_LightPos);
	glEnable(GL_LIGHT0);

	// Enable color tracking
	glEnable(GL_COLOR_MATERIAL);

	// Set Material properties to follow glColor values
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

	// All materials hereafter have full specular reflectivity
	// with a high shine
	glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
	glMateriali(GL_FRONT, GL_SHININESS, 128);

	// Light blue background
	glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

	// Get the plane equation from three points on the ground
	M3DVector4f vPlaneEquation;
	m3dGetPlaneEquation(vPlaneEquation, points[0], points[1], points[2]);

	// Calculate projection matrix to draw shadow on the ground
	m3dMakePlanarShadowMatrix(m_ShadowMat, vPlaneEquation, m_LightPos);

	glEnable(GL_NORMALIZE);

}

void CSp007::RenderLoop() {
	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Draw the ground, we do manual shading to a darker green
	// in the background to give the illusion of depth
	glBegin(GL_QUADS);
		glColor3ub(0, 32, 0);
		glVertex3f(400.0f, -150.0f, -200.0f);
		glVertex3f(-400.0f, -150.0f, -200.0f);
		glColor3ub(0, 255, 0);
		glVertex3f(-400.0f, -150.0f, 200.0f);
		glVertex3f(400.0f, -150.0f, 200.0f);
	glEnd();

	// Save the matrix state and do the rotations
	glPushMatrix();

	// Draw jet at new orientation, put light in correct position
	// before rotating the jet
	glEnable(GL_LIGHTING);
	glLightfv(GL_LIGHT0, GL_POSITION, m_LightPos);
	glRotatef(m_xRot, 1.0f, 0.0f, 0.0f);
	glRotatef(m_yRot, 0.0f, 1.0f, 0.0f);

	this->DrawJet(false);

	// Restore original matrix state
	glPopMatrix();

	// Get ready to draw the shadow and the ground
	// First disable lighting and save the projection state
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_LIGHTING);
	glPushMatrix();

	// Multiply by shadow projection matrix
	glMultMatrixf((GLfloat *) m_ShadowMat);

	// Now rotate the jet around in the new flattend space
	glRotatef(m_xRot, 1.0f, 0.0f, 0.0f);
	glRotatef(m_yRot, 0.0f, 1.0f, 0.0f);

	// Pass true to indicate drawing shadow
	this->DrawJet(true);

	// Restore the projection to normal
	glPopMatrix();

	// Draw the light source
	glPushMatrix();
	glTranslatef(m_LightPos[0], m_LightPos[1], m_LightPos[2]);
	glColor3ub(255, 255, 0);
	glutSolidSphere(5.0f, 10, 10);
	glPopMatrix();

	// Restore lighting state variables
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING);

	SDL_GL_SwapBuffers();
	SDL_Delay(1000 * 1/30);
}

void CSp007::OnEventWndResize(int w, int h) {
	m_ScreenW = w;
	m_ScreenH = h;
	if (h == 0)
		h = 1;
	glViewport(0,0,w,h);

	GLdouble dRatio = (GLdouble)w/(GLdouble)h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(60.0,dRatio,200.0,500.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glTranslatef(0.0f,0.0f,-400.0f);

	glLightfv(GL_LIGHT0,GL_POSITION,m_LightPos);
}

void CSp007::DrawJet(bool bShadow) {
	if (bShadow)
		glColor3ub(0, 0, 0);
	else
		glColor3ub(128, 128, 128);
	M3DVector3f temp[] = {
				// Head of the Plane///////////////////////////////
				{0.0f, 0.0f, 60.0f},{-15.0f, 0.0f, 30.0f},{15.0f, 0.0f, 30.0f},
				{15.0f, 0.0f, 30.0f},{0.0f, 15.0f, 30.0f},{0.0f, 0.0f, 60.0f},
				{0.0f, 0.0f, 60.0f},{0.0f, 15.0f, 30.0f},{-15.0f, 0.0f, 30.0f},
				// Body of the Plane///////////////////////////////
				{-15.0f, 0.0f, 30.0f},{0.0f, 15.0f, 30.0f},{0.0f, 0.0f, -56.0f},
				{0.0f, 0.0f, -56.0f},{0.0f, 15.0f, 30.0f},{15.0f, 0.0f, 30.0f},
				{15.0f, 0.0f, 30.0f},{-15.0f, 0.0f, 30.0f},{0.0f, 0.0f, -56.0f},
				// Left wing
				// Large triangle for bottom of wing
				{0.0f, 2.0f, 27.0f},{-60.0f, 2.0f, -8.0f},{60.0f, 2.0f, -8.0f},
				{60.0f, 2.0f, -8.0f},{0.0f, 7.0f, -8.0f},{0.0f, 2.0f, 27.0f},
				{60.0f, 2.0f, -8.0f},{-60.0f, 2.0f, -8.0f},{0.0f, 7.0f, -8.0f},
				// Other wing top section
				{0.0f, 2.0f, 27.0f},{0.0f, 7.0f, -8.0f},{-60.0f, 2.0f, -8.0f},
				// Tail section///////////////////////////////
				// Bottom of back fin
				{-30.0f, -0.50f, -57.0f},{30.0f, -0.50f, -57.0f},{0.0f, -0.50f, -40.0f},
				// top of left side
				{0.0f, -0.5f, -40.0f},{30.0f, -0.5f, -57.0f},{0.0f, 4.0f, -57.0f},
				// top of right side
				{0.0f, 4.0f, -57.0f},{-30.0f, -0.5f, -57.0f},{0.0f, -0.5f, -40.0f},
				// back of bottom of tail
				{30.0f, -0.5f, -57.0f},{-30.0f, -0.5f, -57.0f},{0.0f, 4.0f, -57.0f},
				// Top of Tail section left
				{0.0f, 0.5f, -40.0f},{3.0f, 0.5f, -57.0f},{0.0f, 25.0f, -65.0f},
				{0.0f, 25.0f, -65.0f},{-3.0f, 0.5f, -57.0f},{0.0f, 0.5f, -40.0f},
				// Back of horizontal section
				{3.0f, 0.5f, -57.0f},{-3.0f, 0.5f, -57.0f},{0.0f, 25.0f, -65.0f},
		};
	glBegin(GL_TRIANGLES);
	for (int i = 0; i < 17 * 3 ; i+=3) {
		GLfloat *p1,*p2,*p3;
		p1 = temp[i];
		p2 = temp[i+1];
		p3 = temp[i+2];
		M3DVector3f vNoraml;
		m3dFindNormal(vNoraml,p1,p2,p3);
		glVertex3fv(p1);
		glVertex3fv(p2);
		glVertex3fv(p3);
		}
	glEnd(); // Of Jet
}

